﻿#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QApplication>
#include <Experiment/ExperimentOperation.h>
#include <QFontDatabase>
#include <QDateTime>
#include "execonfig.h"
#include <QFile>
#include <QTextCodec>
#include <QFontDatabase>
#include <QFont>
#include "QThread"
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QVariant>
#include <QSqlRecord>
#include "execonfig.h"
#include <QQmlContext>
#include <DbHelper.h>
#include <GetMessageInterface.h>
#include <QTranslator>
#include "QQuickWindow"
#include "cMock.h"
#include "logHelper/debugLog.h"
#include <MaintenanceAndCorrection.h>
#include "animation/animationPublicInterface.h"
#include <Connect/UdpClient.h>
#include "animation/practiceAnimation/animationManager_Practice.h"
#include "animation/shiftingAnimation/animationManager_Shifting.h"
#include "animation/purifyAnimation/animationManager_Purify.h"
#include "animationStateRescue.h"
#include "animationParseHEX.h"
#include "camera/cameraProvider.h"
#include "camera/CameraManager.h"
#include "report/printerManager.h"
#include "report/reportManager.h"
#include "cTools.h"
#include "chromatogram/ChromatogramManager.h"
#include "chromatogram/chromatogramChart.h"
#include "ConsumableCode/barCodeManager.h"
#include "inputMethodEventCatch.h"
#include "updateExe.h"
#include "downloadManager.h"
#include "licenseManager/licenseManager.h"
//#include "camera/cameraFboItem.h"
#include "camera/connectCameraInterface.h"
#include <QQuickWindow>
#include <QQuickView>
#include <QElapsedTimer>
#include "animationCommObject_Purify.h"
#include "QmlLanguage.h"
#include <QMessageBox>
#include "report/excelExporter.h"

//speechModuleThread *spmoduleth;    //语音模块
//DataSerialportClient *serialPortClient;
int npwhfl=0; // 1开 0关

QQmlApplicationEngine* gQmlEngine;

void onTimeout() {
    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);
    QDateTime current=QDateTime::currentDateTime();
    QString dateStr=current.toString("yyyy-MM-dd");
    QString sql=QString("Select count(*) Num From DataStatistics Where StaticDate='%1'").arg(dateStr);
    query.exec(sql);
    int num = 0;
    while (query.next()) {
        num=query.value("Num").toInt();
    }
    if(num>0){
        sql=QString("Update DataStatistics Set EquOperatingTime=(EquOperatingTime*3600.0+60)/3600.0 Where StaticDate='%1'").arg(dateStr);
        query.exec(sql);
    }
    else
    {
        sql=QString("Insert into DataStatistics Values('%1','0','0','0','0','0','0','0','0')").arg(dateStr);
        query.exec(sql);

        sql=QString("Update DataStatistics Set EquOperatingTime=(EquOperatingTime*3600.0+60)/3600.0 Where StaticDate='%1'").arg(dateStr);
        query.exec(sql);
    }
}

void onHeartTimeout(){
    UdpClient *udpClient;
    udpClient=UdpClient::getInstance();

    if(udpClient->IsOnline())
    {
        QString info =CommCommand::I().connectToLc();
        udpClient->ClientSendingData(CommonHelper::Common().GetSendData(info));
        StaticProperties::heartMsg=false;
    }
    else
    {
        QString info =CommCommand::I().connectToLc();
        udpClient->ClientSendingData(CommonHelper::Common().GetSendData(info));
        StaticProperties::firstConnect=true;
        CommonHelper::Common().setDefaultDetectionParameters();
        QMLSignal::I().emitCommunicationStatus(1);     // 发信号通知前端
    }

}

void onReadTargetRelease(){

    UdpClient *udpClient;
    udpClient=UdpClient::getInstance();

    if(udpClient->IsOnline())
    {
        QString info ="62 00 00 3C 00 06 2A 21 E7 2F 55 AA";
        udpClient->ClientSendingData(CommonHelper::Common().GetSendData(info));
    }
}

void initDatabase(){

    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);

    // 摄像头
    QString sql = "CREATE TABLE IF NOT EXISTS CameraIpInfo (Type Numeric PRIMARY KEY, CameraType Text, Ip Text, Port Text, Username Text, Password Text)";
    query.exec(sql);

    // 导出报告的ReportInfo
    sql = "CREATE TABLE IF NOT EXISTS ReportInfo ("
          "Serial Numeric PRIMARY KEY, "
          "ExpName Text, "
          "ExpType Text, "
          "ExpStartTime Text, "
          "ExpEndTime Text, "
          "ExpDuration Text, "
          "Operator Text, "
          "EquName Text, "
          "ConsumableName Text, "
          "ConsumableCode Text, "
          "SampleHalfLife Text, "
          "HalfLifeDate Text, "
          "Memo Text, "
          "ValveStartTime Text, "
          "ValveDelayTime Text, "
          "ValveEndTime Text, "
          "Conc Text"
          ")";
    query.exec(sql);

    // ReportDetails中插入新的列Memo
    sql = "ALTER TABLE ReportDetail ADD COLUMN Memo TEXT";
    query.exec(sql);
    sql = "ALTER TABLE ExperimentDetail ADD COLUMN UnionId TEXT";
    query.exec(sql);


}


int main(int argc, char *argv[])
{
    __LOG_INFO("=============================== main函数加载 ===============================");

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
//    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
//    QApplication::setHighDpiScaleFactorRoundingPolicy(
//                Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);

    QApplication app(argc, argv);
    QSharedMemory shared_memory;
    shared_memory.setKey(QString("111111"));
    if(shared_memory.attach()){
        QMessageBox::information(nullptr,"提示","软件已打开！", QMessageBox::Ok);
        return 0;
    }

    app.setWindowIcon(QIcon(":/logo.ico"));
    int fontId = QFontDatabase::addApplicationFont(":/fonts/AlibabaPuHuiTi-3-55-Regular.ttf");      // 字体设置
    if(fontId != -1){
        QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId);
        if(fontFamilies.isEmpty()){
            qDebug("设置字体失败");
        }
        QString familyName = fontFamilies.first();
        QFont font(familyName, 10);
        app.setFont(font);
    }else{
        qDebug("设置字体失败");
    }

    __LOG_INFO("=============================== 设置字体完成 ===============================");


    QQmlApplicationEngine engine;
    gQmlEngine = &engine;

    qmlRegisterType<InputMethodEventCatch, 1>("CCustomClass", 1, 0, "InputMethodEventCatch");     // 注册C++类到QML
    //    qmlRegisterType<CameraFBOItem, 1>("CCustomClass", 1, 0, "CameraFBOItem");    // 注册C++类到QML


    qmlRegisterType<CustomChartCurveInfoObject, 1>("CCustomClass", 1, 0, "ChartInfoObject");
    qmlRegisterType<CustomChart, 1>("CCustomClass", 1, 0, "CCustomChart");   // 注册这个主要是为了用里面的Enum类型
    qmlRegisterType<AnimationCommObject_Purify, 1>("CObjectAnimation", 1, 0, "CommObject_Purify");


    QQuickView view;

    view.setResizeMode(QQuickView::SizeRootObjectToView);

    view.setSource(QUrl(QStringLiteral("qrc:/Splash.qml")));

//    QElapsedTimer t;
//    t.start();

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
//    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    // ============== 修改部分：替换 while 循环 ==============
    //    QTimer::singleShot(3000, [&view, &engine]() {


    //    });


    //    QQmlApplicationEngine engine;
    //    const QUrl url(QStringLiteral("qrc:/main.qml"));
    //    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
    //                     &app, [url](QObject *obj, const QUrl &objUrl) {
    //        if (!obj && url == objUrl)
    //            QCoreApplication::exit(-1);
    //    }, Qt::QueuedConnection);


    CMock* cmock = new CMock();
    engine.rootContext()->setContextProperty("CMock", cmock);

    ExeConfig *execonf = new ExeConfig();
    engine.rootContext()->setContextProperty("CExeConfig", execonf);
    //    DefaultSet *defaults = new DefaultSet();
    //    engine.rootContext()->setContextProperty("CDefaultS",defaults);

    ExperimentOperation *comMethod = new ExperimentOperation();
    engine.rootContext()->setContextProperty("CommunicationMethod", comMethod);

    GetMessageInterface *getMessage = new GetMessageInterface();
    engine.rootContext()->setContextProperty("CGetMessageInterface", getMessage);
    engine.rootContext()->setContextProperty("CSignal", &QMLSignal::I());
    ReportManager::I().setGmiInterface(getMessage);

    //    ReportInterface* reportInterface = new ReportInterface();
    //    engine.rootContext()->setContextProperty("CReport", reportInterface);

    MaintenanceAndCorrection* Maintenance = new MaintenanceAndCorrection();
    engine.rootContext()->setContextProperty("CMaintenance", Maintenance);

    engine.rootContext()->setContextProperty("CAnimationPurify", &AnimationManager_Purify::I());
    engine.rootContext()->setContextProperty("CAnimationShifting", &AnimationManager_Shifting::I());
    engine.rootContext()->setContextProperty("CAnimationPractice", &AnimationManager_Practice::I());
    engine.rootContext()->setContextProperty("CAnimation", &AnimationPublicInterface::I());
    engine.rootContext()->setContextProperty("CAnimationRescue", &AnimationStateRescue::I());

    QmlLanguage qmlLanguage(app, engine);
    engine.rootContext()->setContextProperty("qmlLanguage", &qmlLanguage);


    AnimationParseHEX::I().initState(AnimationManager_Shifting::I()._state, AnimationManager_Practice::I()._state, AnimationManager_Purify::I()._state_equ);
    AnimationPublicInterface::I().initState(AnimationManager_Shifting::I()._state, AnimationManager_Practice::I()._state, AnimationManager_Purify::I()._state_equ);     // 为啥我要把这几个单例做成指针塞进去……



    ChromatogramChart* chromChart = new ChromatogramChart();
    ChromatogramManager* chromManager = new ChromatogramManager();
    chromManager->_chart = chromChart;
    chromManager->_msgInterface = getMessage;      // 给能谱图后端提供接口
    engine.rootContext()->setContextProperty("CChromChart", chromChart);
    engine.rootContext()->setContextProperty("CChromManager", chromManager);
    chromManager->clearChart();



    //数据统计计时器 1分钟触发一次
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, &onTimeout);
    timer.start(60000);

    StaticProperties::firstConnect=true;

    //自动连接UDP通信
    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);
    QString ip,port;
    QString sql="Select Ip,Port From IpInfo Where ConnectType='0'";
    query.exec(sql);
    while (query.next()) {
        ip=query.value("Ip").toString();
        port=query.value("Port").toString();
    }

    initDatabase();

    UdpClient *udpClient= UdpClient::getInstance();
    udpClient->ClientConnectToHost(ip, port.toInt());
    QString sendInfo=CommCommand::I().connectToLc();
    udpClient->ClientSendingData(CommonHelper::Common().GetSendData(sendInfo));

    CpsUdpClient *cpsudpClient= CpsUdpClient::getInstance();
    cpsudpClient->ClientConnectToHost(ip, 8090);

    //心跳计时器 每隔5秒触发一次
    QTimer heartTimer;
    QObject::connect(&heartTimer, &QTimer::timeout, &onHeartTimeout);
    heartTimer.start(15000);

    QTimer targetReleaseTimer;
    QObject::connect(&targetReleaseTimer, &QTimer::timeout, &onReadTargetRelease);
    targetReleaseTimer.start(4000);

    //    sql="Select Port From IpInfo Where ConnectType='3'";
    //    query.exec(sql);
    //    while (query.next()) {
    //        port=query.value("Port").toString();
    //    }
    //    serialPortClient = new DataSerialportClient();
    //    serialPortClient->startAutoSend(1000, port);

    sql=QString("Update ModuleResetStatus set Status=0");
    query.exec(sql);

    CTools* tools = new CTools();
    engine.rootContext()->setContextProperty("CTools", tools);


    // 启动摄像头
    engine.rootContext()->setContextProperty("CCamera", &CameraManager::I());
    engine.rootContext()->setContextProperty("CCameraInterface", &ConnectCameraInterface::I());


    // 授权码
    engine.rootContext()->setContextProperty("CLicense", &(LicenseManager::I()));       //
    // 打印报告
    engine.rootContext()->setContextProperty("CReport", &ReportManager::I());
    engine.rootContext()->setContextProperty("CPrinter", &PrinterManager::I());
    PrinterManager::I().initProvider(&engine);
    ExcelExporter* eexporter = new ExcelExporter();
    engine.rootContext()->setContextProperty("CExcelReport", eexporter);
    // 下载
    engine.rootContext()->setContextProperty("CDownload", &DownloadManager::I());
    // 耗材编码
    engine.rootContext()->setContextProperty("CBarCode", &BarCodeManager::I());

    StaticProperties::expLogList={
        {
            {1, {
                 {"name", "Item 1"}
             }}
        },

        // 第二个元素
        {
            {1, {
                 {"name", "Item 2"}
             }}
        },
        // 第三个元素
        {
            {2, {
                 {"name", "Item 3"}
             }}
        },

        // 第四个元素
        {
            {3, {
                 {"name", "Item 4"}
             }}
        }
    };

#ifdef Q_OS_WINDOWS
    SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);      // 禁止系统休眠
#endif

    //    spmoduleth = new speechModuleThread();

    UpdateExe* exeUpdater = new UpdateExe();
    engine.rootContext()->setContextProperty("CExeUpdater", exeUpdater);

    CommonHelper::Common().setDefaultDetectionParameters();

    engine.load(url);
    view.hide();
    //    view.hide();
    if(shared_memory.create(1)) //创建1byte的共享内存段
    {
        return app.exec();
    }
    StaticProperties::existSoft=false;

    return 0;
}
